package org.microframework.cloud.logs.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.microframework.base.core.web.page.PageQuery;
import org.microframework.cloud.logs.model.domain.ApiLog;
import org.microframework.cloud.logs.model.dto.ApiLogDTO;
import org.microframework.cloud.logs.model.dto.ApiLogQueryDTO;
import org.microframework.cloud.logs.model.dto.ApiLogStatsDTO;
import org.microframework.cloud.logs.service.IApiLogService;
import org.springframework.stereotype.Service;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;

/**
 * API调用日志服务实现类
 *
 * @author zs
 * @version 1.0.0
 * @since 2024-06-14
 * @description 实现API调用日志的查询、删除、导出、统计等功能
 */
@Service
public class ApiLogServiceImpl implements IApiLogService {
    
    /**
     * 查询API调用日志详情
     */
    @Override
    public ApiLogDTO selectApiLogById(String id) {
        if (StringUtils.isEmpty(id)) {
            return null;
        }
        Record record = Db.findById(ApiLog.TABLE_NAME, id);
        if (record == null) {
            return null;
        }
        return convertToApiLogDTO(record);
    }

    /**
     * 查询API调用日志列表（分页）
     */
    @Override
    public Page<ApiLogDTO> selectApiLogList(PageQuery<ApiLog> pageQuery) {
        // 构建查询条件
        StringBuilder sqlBuilder = new StringBuilder("FROM " + ApiLog.TABLE_NAME + " a WHERE 1=1");
        List<Object> params = new ArrayList<>();
        
        ApiLog query = pageQuery.getQuery();
        if (query != null) {
            if (StringUtils.isNotEmpty(query.getServiceName())) {
                sqlBuilder.append(" AND a.service_name LIKE ?");
                params.add("%" + query.getServiceName() + "%");
            }
            if (StringUtils.isNotEmpty(query.getServiceIp())) {
                sqlBuilder.append(" AND a.service_ip LIKE ?");
                params.add("%" + query.getServiceIp() + "%");
            }
            if (StringUtils.isNotEmpty(query.getApiName())) {
                sqlBuilder.append(" AND a.api_name LIKE ?");
                params.add("%" + query.getApiName() + "%");
            }
            if (StringUtils.isNotEmpty(query.getMethod())) {
                sqlBuilder.append(" AND a.method = ?");
                params.add(query.getMethod());
            }
            if (StringUtils.isNotEmpty(query.getRequestPath())) {
                sqlBuilder.append(" AND a.request_path LIKE ?");
                params.add("%" + query.getRequestPath() + "%");
            }
            if (query.getResponseStatus() != null) {
                sqlBuilder.append(" AND a.response_status = ?");
                params.add(query.getResponseStatus());
            }
            if (query.getStatus() != null) {
                sqlBuilder.append(" AND a.status = ?");
                params.add(query.getStatus());
            }
            if (StringUtils.isNotEmpty(query.getCaller())) {
                sqlBuilder.append(" AND a.caller LIKE ?");
                params.add("%" + query.getCaller() + "%");
            }
            if (StringUtils.isNotEmpty(query.getTraceId())) {
                sqlBuilder.append(" AND a.trace_id = ?");
                params.add(query.getTraceId());
            }
        }
        
        // 使用JFinal分页查询
        String select = "SELECT a.*";
        Page<Record> page = Db.paginate(pageQuery.getPageNumber(), pageQuery.getPageSize(), select, sqlBuilder.toString(), params.toArray());
        
        // 转换为DTO
        List<ApiLogDTO> dtoList = new ArrayList<>();
        for (Record record : page.getList()) {
            dtoList.add(convertToApiLogDTO(record));
        }
        
        return new Page<>(dtoList, page.getPageNumber(), page.getPageSize(), page.getTotalPage(), page.getTotalRow());
    }

    /**
     * 查询API调用日志列表（不分页）
     */
    @Override
    public List<ApiLogDTO> selectApiLogList(ApiLogQueryDTO queryDTO) {
        // 构建查询条件
        StringBuilder sqlBuilder = new StringBuilder("FROM " + ApiLog.TABLE_NAME + " a WHERE 1=1");
        List<Object> params = new ArrayList<>();
        
        if (queryDTO != null) {
            if (StringUtils.isNotEmpty(queryDTO.getServiceName())) {
                sqlBuilder.append(" AND a.service_name LIKE ?");
                params.add("%" + queryDTO.getServiceName() + "%");
            }
            if (StringUtils.isNotEmpty(queryDTO.getServiceIp())) {
                sqlBuilder.append(" AND a.service_ip LIKE ?");
                params.add("%" + queryDTO.getServiceIp() + "%");
            }
            if (StringUtils.isNotEmpty(queryDTO.getApiName())) {
                sqlBuilder.append(" AND a.api_name LIKE ?");
                params.add("%" + queryDTO.getApiName() + "%");
            }
            if (StringUtils.isNotEmpty(queryDTO.getMethod())) {
                sqlBuilder.append(" AND a.method = ?");
                params.add(queryDTO.getMethod());
            }
            if (StringUtils.isNotEmpty(queryDTO.getRequestPath())) {
                sqlBuilder.append(" AND a.request_path LIKE ?");
                params.add("%" + queryDTO.getRequestPath() + "%");
            }
            if (queryDTO.getResponseStatus() != null) {
                sqlBuilder.append(" AND a.response_status = ?");
                params.add(queryDTO.getResponseStatus());
            }
            if (queryDTO.getStatus() != null) {
                sqlBuilder.append(" AND a.status = ?");
                params.add(queryDTO.getStatus());
            }
            if (StringUtils.isNotEmpty(queryDTO.getCaller())) {
                sqlBuilder.append(" AND a.caller LIKE ?");
                params.add("%" + queryDTO.getCaller() + "%");
            }
            if (StringUtils.isNotEmpty(queryDTO.getTraceId())) {
                sqlBuilder.append(" AND a.trace_id = ?");
                params.add(queryDTO.getTraceId());
            }
        }
        
        // 查询数据
        String select = "SELECT a.*";
        List<Record> records = Db.find(select + sqlBuilder.toString(), params.toArray());
        
        // 转换为DTO
        List<ApiLogDTO> dtoList = new ArrayList<>();
        for (Record record : records) {
            dtoList.add(convertToApiLogDTO(record));
        }
        
        return dtoList;
    }

    /**
     * 新增API调用日志
     */
    @Override
    public int insertApiLog(ApiLog apiLog) {
        if (apiLog == null) {
            return 0;
        }
        
        // 设置ID和时间
        if (StringUtils.isEmpty(apiLog.getId())) {
            apiLog.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        }
        if (apiLog.getCallTime() == null) {
            apiLog.setCallTime(new Date());
        }
        
        Record record = new Record();
        record.set("id", apiLog.getId());
        record.set("service_name", apiLog.getServiceName());
        record.set("service_ip", apiLog.getServiceIp());
        record.set("api_name", apiLog.getApiName());
        record.set("method", apiLog.getMethod());
        record.set("request_path", apiLog.getRequestPath());
        record.set("request_params", apiLog.getRequestParams());
        record.set("request_headers", apiLog.getRequestHeaders());
        record.set("response_status", apiLog.getResponseStatus());
        record.set("response_body", apiLog.getResponseBody());
        record.set("duration", apiLog.getDuration());
        record.set("status", apiLog.getStatus());
        record.set("error_message", apiLog.getErrorMessage());
        record.set("call_time", apiLog.getCallTime());
        record.set("caller", apiLog.getCaller());
        record.set("trace_id", apiLog.getTraceId());
        record.set("create_time", new Date());
        
        try {
            return Db.save(ApiLog.TABLE_NAME, record) ? 1 : 0;
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 修改API调用日志
     */
    @Override
    public int updateApiLog(ApiLog apiLog) {
        if (apiLog == null || StringUtils.isEmpty(apiLog.getId())) {
            return 0;
        }
        
        // 先获取原记录
        Record record = Db.findById(ApiLog.TABLE_NAME, apiLog.getId());
        if (record == null) {
            return 0;
        }
        
        // 更新数据
        if (StringUtils.isNotEmpty(apiLog.getServiceName())) {
            record.set("service_name", apiLog.getServiceName());
        }
        if (StringUtils.isNotEmpty(apiLog.getServiceIp())) {
            record.set("service_ip", apiLog.getServiceIp());
        }
        if (StringUtils.isNotEmpty(apiLog.getApiName())) {
            record.set("api_name", apiLog.getApiName());
        }
        if (StringUtils.isNotEmpty(apiLog.getMethod())) {
            record.set("method", apiLog.getMethod());
        }
        if (StringUtils.isNotEmpty(apiLog.getRequestPath())) {
            record.set("request_path", apiLog.getRequestPath());
        }
        if (StringUtils.isNotEmpty(apiLog.getRequestParams())) {
            record.set("request_params", apiLog.getRequestParams());
        }
        if (StringUtils.isNotEmpty(apiLog.getRequestHeaders())) {
            record.set("request_headers", apiLog.getRequestHeaders());
        }
        if (apiLog.getResponseStatus() != null) {
            record.set("response_status", apiLog.getResponseStatus());
        }
        if (StringUtils.isNotEmpty(apiLog.getResponseBody())) {
            record.set("response_body", apiLog.getResponseBody());
        }
        if (apiLog.getDuration() != null) {
            record.set("duration", apiLog.getDuration());
        }
        if (apiLog.getStatus() != null) {
            record.set("status", apiLog.getStatus());
        }
        if (StringUtils.isNotEmpty(apiLog.getErrorMessage())) {
            record.set("error_message", apiLog.getErrorMessage());
        }
        if (apiLog.getCallTime() != null) {
            record.set("call_time", apiLog.getCallTime());
        }
        if (StringUtils.isNotEmpty(apiLog.getCaller())) {
            record.set("caller", apiLog.getCaller());
        }
        if (StringUtils.isNotEmpty(apiLog.getTraceId())) {
            record.set("trace_id", apiLog.getTraceId());
        }
        
        record.set("update_time", new Date());
        
        try {
            return Db.update(ApiLog.TABLE_NAME, record) ? 1 : 0;
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 批量删除API调用日志
     */
    @Override
    public int deleteApiLogByIds(String ids) {
        if (StringUtils.isEmpty(ids)) {
            return 0;
        }
        
        String[] idArray = ids.split(",");
        int successCount = 0;
        
        for (String id : idArray) {
            try {
                boolean success = Db.deleteById(ApiLog.TABLE_NAME, id);
                if (success) {
                    successCount++;
                }
            } catch (Exception e) {
                // 忽略异常
            }
        }
        
        return successCount;
    }

    /**
     * 删除单个API调用日志
     */
    @Override
    public int deleteApiLogById(String id) {
        if (StringUtils.isEmpty(id)) {
            return 0;
        }
        
        try {
            return Db.deleteById(ApiLog.TABLE_NAME, id) ? 1 : 0;
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 清空API调用日志
     */
    @Override
    public boolean cleanApiLog() {
        try {
            Db.update("TRUNCATE TABLE " + ApiLog.TABLE_NAME);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 导出API调用日志
     */
    @Override
    public Object exportApiLog(ApiLogQueryDTO queryDTO) {
        List<ApiLogDTO> list = selectApiLogList(queryDTO);
        // TODO: 导出逻辑，转换为Excel或CSV
        return list;
    }

    /**
     * 获取API调用统计数据
     */
    @Override
    public ApiLogStatsDTO getApiCallStatistics() {
        ApiLogStatsDTO stats = new ApiLogStatsDTO();
        
        // 获取总调用次数
        stats.setTotalCount(getTotalApiLogCount());
        
        // 获取错误调用次数
        stats.setErrorCount(getErrorApiLogCount());
        
        // 获取调用量前10的API
        stats.setApiTopList(getTopApiList());
        
        return stats;
    }
    
    /**
     * 获取API日志总数
     */
    private long getTotalApiLogCount() {
        try {
            return Db.queryLong("SELECT COUNT(1) FROM " + ApiLog.TABLE_NAME);
        } catch (Exception e) {
            return 0;
        }
    }
    
    /**
     * 获取错误API日志数量
     */
    private long getErrorApiLogCount() {
        try {
            return Db.queryLong("SELECT COUNT(1) FROM " + ApiLog.TABLE_NAME + " WHERE status = 1");
        } catch (Exception e) {
            return 0;
        }
    }
    
    /**
     * 获取调用量前10的API
     */
    private List<ApiLogStatsDTO.ApiTopDTO> getTopApiList() {
        try {
            List<Record> records = Db.find("SELECT api_name, COUNT(1) as count, AVG(duration) as avg_duration " +
                    "FROM " + ApiLog.TABLE_NAME + " GROUP BY api_name ORDER BY count DESC LIMIT 10");
            
            List<ApiLogStatsDTO.ApiTopDTO> result = new ArrayList<>();
            for (Record record : records) {
                ApiLogStatsDTO.ApiTopDTO item = new ApiLogStatsDTO.ApiTopDTO();
                item.setApiName(record.getStr("api_name"));
                item.setCount(record.getLong("count"));
                item.setAvgDuration(record.getBigDecimal("avg_duration").doubleValue());
                result.add(item);
            }
            
            return result;
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }
    
    /**
     * 将Record转换为ApiLogDTO
     */
    private ApiLogDTO convertToApiLogDTO(Record record) {
        if (record == null) {
            return null;
        }
        
        ApiLogDTO dto = new ApiLogDTO();
        dto.setId(record.getStr("id"));
        dto.setServiceName(record.getStr("service_name"));
        dto.setServiceIp(record.getStr("service_ip"));
        dto.setApiName(record.getStr("api_name"));
        dto.setMethod(record.getStr("method"));
        dto.setRequestPath(record.getStr("request_path"));
        dto.setRequestParams(record.getStr("request_params"));
        dto.setRequestHeaders(record.getStr("request_headers"));
        dto.setResponseStatus(record.getInt("response_status"));
        dto.setResponseBody(record.getStr("response_body"));
        dto.setDuration(record.getLong("duration"));
        dto.setStatus(record.getInt("status"));
        dto.setErrorMessage(record.getStr("error_message"));
        dto.setCallTime(record.getDate("call_time"));
        dto.setCaller(record.getStr("caller"));
        dto.setTraceId(record.getStr("trace_id"));
        dto.setCreateTime(record.getDate("create_time"));
        dto.setUpdateTime(record.getDate("update_time"));
        
        return dto;
    }
} 